内容简述:对象和类、方法和this、数组、继承、访问控制权限、static、final、抽象类、接口、内部类、对象内存管理。
一、对象和类
高质量的代码:
复用性好,扩展性好,维护性好,可移植性好,健壮性好,效率高。
1. 什么是类?什么是对象?
1) 现实世界是由很多很多对象组成的
基于对象抽象出了类
2) 对象:真实存在的单个的个体
类:类型/类别,代表一类个体
3) 类中可以包括:
3.1)变量:所有对象所共有的属性/特征
3.2)方法:所有对象所共有的行为
4)一个类可以创建多个对象
同一类型的多个对象,结构相同,数据不同
5)类是对象的模板,对象是类的具体的实例
二、方法和this
1. 方法的签名:方法名 + 参数列表
2. 方法的重载(Overload)
1) 发生在一个类中,方法名称相同,参数列表不同
2) 编译器在编译时会根据方法签名自动绑定调用的方法
3.构造方法
1)给成员变量赋初值
2)与类同名,没有返回值类型,有返回值的不是构造方法
3)在创建对象是被自动调用
4)若自己不写构造方法,则编译器默认提供一个无参构造方法
注意:若自己写了构造方法,则不再默认提供,一般在重载有参构造前先写一个空的无参构造。
5)构造方法可以重载
4. this
指代当前对象,哪个对象调方法指的就是哪个对象
只能用在方法中,方法中访问成员变量之前默认有个“this.”
this的用法:
1) this.成员变量名————–访问成员变量
2) this.方法名()—————–调用方法(一般不用)
3) this()————————调用构造方法
三、数组,继承(上)
1. 引用类型数组
1)Student[] stus = new Student[3];
stus[0] = new Student();
stus[1] = new Student();
stus[2] = new Student();
2)Student[] stus = new Student[]{
new Student(),
new Student(),
new Student()
};
3)int [ ] [ ] arr = new int[3][ ];
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int [2];
arr[1][0]=100; //将arr中第2个元素中的第1个元素赋值为10
4)int [ ] [ ] arr = new int[3][4];
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
arr[i][j]=100;
}
}
(对象放在栈里面,基本类型的值是在栈里面的,
引用变量的值是在堆中,函数放在方法区.)
2. null:空,没有指向任何对象
若引用的值为null,则该引用不能再进行任何操作了
若操作,则发生NullPointerException空指针异常
3. 继承
1)作用:减少代码重复、提高代码的复用性
2)通过extends来实现继承
3)父类:所有子类所共有的属性和行为
子类:子类所特有的属性和行为
4)子类继承父类后,子类具有:子类+父类所有的属性和方法
5)一个父类可以创建多个子类
一个子类只能有一个父类——单一继承
6)继承具有传递性
7)java规定:构造子类之前必须先构造父类
在子类构造方法中若没有调用父类构造方法,则默认super()来调用父类的无参构造
若子类构造方法中自己调用了父类的构造方法,则不再默认提供
4. super:指代当前对象的父类对象
super的用法:
1) super.成员变量名——-访问父类的成员变量
2) super.方法名()———-调用父类的方法
3) super()—————–调用父类的构造方法
四、继承(下)
1. 方法的重写:重新写、覆盖
1) 发生在父子类中,方法名称相同,参数列表相同,方法体不同
2) 重写方法被调用时,看对象的类型
2. 重写遵循”两同两小一大“原则
1)两同:
1.1)方法名称相同
1.2) 参数列表相同
2)两小:
2.1)子类方法的返回值类型小于或等于父类的
a)void时,必须相等
b)基本数据类型时,必须相等
c)引用数据类型时,小于或等于
2.2)子类抛出的异常要小于或等于父类的——-异常之后
3)一大:
3.1)子类方法的访问权限大于或等于父类的——访问控制修饰符之后
3. 重写与重载的区别——–常见面试题
1)重写(Override):
1.1)发生在父子类中,方法名称相同,参数列表相同,方法体不同
1.2)遵循“运行期绑定“,看对象的类型来调用方法
2)重载(Overload):
2.1)发生在一个类中,方法名称相同,参数列表不同,方法体不同
2.2)遵循“编译期绑定“,看引用的类型来绑定方法
4. 向上造型
1)父类型的引用指向子类的对象
2)能点出来什么,看引用的类型
五、访问控制、static和final
1. package和import
包命名的建议:
域名反写 . 项目名称 . 模板名称 . 类名
cn.tedu . aproject .
com.taobao . bproject .
com.baidu .
package:
1) 作用:避免类名的冲突
2) 同包中的类不能同名的
3) 类的全称:包名.类名
4) 建议:所有字母都小写
import:
1) 同包中的类可以直接访问,不同包中的类不能直接访问
不同包中的类访问有两种方法:
1.1) 先import声明类再使用类——–建议
1.2) 类的全称———————–太繁琐
2. 访问控制修饰符(抽象方法的访问权限默认都是public)
1) public:公共的,任何类
2) protected:受保护的,本类、子类、同包类
3) 默认的:什么也不写,本类、同包类
4) private:私有的,本类,内部类
说明:
1) 类的访问修饰为public和默认的
2) 类中成员的访问修饰如上4种都可以
3. static:静态的
1) 静态变量:
1.1) 由static修饰的
1.2) 属于类的,存储在方法区中,只有一份
1.3) 常常通过类名来访问
1.4) 何时用:所有对象所共享的数据(图片、音频、视频)
2) 静态方法:
2.1)由static修饰的
2.2)属于类的,存储在方法区中,只有一份
2.3)常常通过类名点来访问
2.4)静态方法没有隐式的this传递,
静态方法中不能直接访问实例成员(本类中的非静态成员变量+非静态成员方法)
2.5)何时用:方法的操作仅与参数相关而与对象无关
3) 静态块:
3.1)在类被加载期间自动执行,
因为类只被加载一次,所以静态块也只执行一次
3.2)何时用:加载/初始化静态资源(图片、音频、视频等)
4. final:最终的—————-单独应用的几率很小
1) 修饰变量:变量不能被改变
2) 修饰方法:方法不能被重写
3) 修饰类:类不能被继承
5. static final 常量—————-应用率高
1) 必须声明同时初始化
2) 通过类名来访问,不能被改变
3) 建议:常量名所有字母都大写,多个单词用下划线分隔
4) 编译器在编译时将常量直接替换为具体的值,效率高
5) 某个数据永远不会改变,并且还经常使用
补充:
1.数据(变量)私有化,行为(方法)公开化
2.成员变量:
1)实例变量:没有static修饰的,属于对象的,存储在堆中的,
有几个对象就有几份
通过对象名点来访问
2)静态变量:由static修饰的,属于类的,存储在方法区中
只有一份
通过类名来访问
六、抽象类、接口和内部类(上)
1. 抽象方法
1) 由abstract修饰
2) 只有方法的定义,没有具体的实现(连{ }都没有)
3)抽象方法的访问权限默认都是public
2. 抽象类
1) 由abstract修饰
2) 包含抽象方法的类必须是抽象类
不包含抽象方法的类也可以声明为抽象类—-我乐意
3) 抽象类不能被实例化
4) 抽象类是需要被继承的,子类:
4.1)必须重写所有的抽象方法———变不完整为完整
4.2)也声明为抽象类————-一般不这样做
设计规则:
1) 将所有子类共有的属性和行为,抽象到父类中
2) 所有子类行为都一样———–设计为普通方法
所有子类行为不一样———–设计为抽象方法
5) 抽象类的意义:
5.1)封装子类共有的属性和行为——-代码复用
5.2)为所有子类提供了统一的类型—–向上造型
5.3)可以包含抽象方法,为所有子类提供统一的入口
子类的具体实现不同,但方法的定义是一致的
七、抽象类、接口和内部类(下)
1. 接口
1)是一种数据类型(引用类型)
2)由interface定义的
3)接口中只能包含常量和抽象方法
4)接口不能被实例化
5)接口时需要被实现(继承)的,实现类(子类):
必须重写接口中的所有抽象方法
6)一个类可以实现多个接口,用逗号分隔
若又继承又实现时,应先继承后实现
7)接口可以继承接口
1 | interface Inter1 { |
2. 多态
1)多态的意义:
1.1)同一类型的引用,在指向不同的对象时,有不同的实现;
—————-行为的多态:cut()、run()
1.2)同一个对象,被造型为不同的类型时,有不同的功能;
—————-对象的多态;我、水
3. 多态的表现形式
1)重写(Override):
1.1)发生在父子类中,方法名称相同,参数列表相同,方法体不同
1.2)遵循“运行期绑定“,看对象的类型来调用方法
2)重载(Overload):
2.1)发生在一个类中,方法名称相同,参数列表不同,方法体不同
2.2)遵循“编译期绑定“,看引用的类型来绑定方法
4. 向上造型
1)父类型的引用指向子类的对象;
2)能造型成为的类型有:父类 + 所实现的接口;
3)能点出来什么,看引用的类型。
5. 强制类型转换(成功的条件有两种)
1)引用所指向的对象,就是该类型(条件一)
2)引用所指向的对象,实现了该接口(条件二)
1 | Aoo o1 = new Boo(); // 向上造型(自动类型转换) |
注意:强转时若不符合如上两个条件,则发生ClassCastException类型转换异常。
建议在强转之前先通过 instanceof 来判断,引用所指向的对象是否是该类型。
1 | Aoo o1 = new Boo(); // 向上造型(自动类型转换) |
八、对象内存管理
1. 引用类型画等号
1)指向同一个对象;
2)对一个引用的修改会影响另一个引用。
2. 基本类型画等号
1)赋值;
2)对一个变量的修改不会影响另一个变量。
2. 内存管理:由JVM来管理
1)堆:
1.1)存储所有new出来的对象(包括实例变量)
1.2)垃圾:没有任何引用所指向的对象;
垃圾回收器(GC)不定时到内存中去清扫垃圾;
垃圾回收器的回收过程是透明的(看不到的);
并不是一发现垃圾九立即回收;
调用 System.gc() 是建议虚拟机尽快调用 GC 来回收垃圾。
1.3)内存泄漏:不再使用的内存还没有被及时的回收
建议:不再使用的内存及时将引用设置为 null。
1.4)实例变量的生命周期:
创建对象时存在堆中,对象被回收时一并被回收。
2)栈:
2.1)存储正在调用的方法中的所有局部变量(包括参数)
2.2)调用方法时会在栈中为该方法分配一块对应的栈帧,
栈帧中存储方法中的局部变量(包含参数),
方法调用完成时,栈帧被清除,局部变量一并失效
2.3)局部变量的生命周期:
调用方法时存在栈中,方法结束时与栈帧一并被清除。
实例变量:
1)类中,方法中
2)创建对象时存储在堆中,对象被回收时一并被回收
3)有默认值
局部变量:
1)方法中
2)调用方法时存储在栈中,方法结束时与栈帧一并被清除
3)没有默认值
- 一个运行的Java程序从开始到结束会有多次方法的调用,JVM会为每一个方法的调用在栈中分配一个对应的空间,这个空间成为该方法的栈帧。
- 一个栈帧对应一个正在调用中的方法,栈帧中存储了该方法的参数,局部变量等数据。当某一个方法调用完成后,其对应的栈帧将被请出,局部变量失效。
3)方法区:
3.1)存储.class字节码文件(包括方法、静态变量);
3.2)方法只有一份;
实例化class的时候的执行顺序:
1)方法区 2)堆 3)栈
面向对象的三大特性:
1.封装:
1)类:封装的对象的属性和行为;
2)方法:封装了具体的业务逻辑功能行为
3)访问控制符:封装的具体的访问权限
2.继承:
1)作用:实现代码的复用,减少代码的重复;
2)通过 extends 来继承,通过 implements 来实现;
3)单一继承,多接口实现;
4)传递性
3.多态:
1)行为的多态、对象的多态;
2)向上造型、强制类型转换、instanceof判断
3)多态的表现形式:
3.1)重写(Override):
3.1.1)发生在父子类中,方法名称相同,参数列表相同,方法体不同
3.1.2)遵循“运行期绑定“,看对象的类型来调用方法
3.2)重载(Overload):
3.2.1)发生在一个类中,方法名称相同,参数列表不同,方法体不同
3.2.2)遵循“编译期绑定“,看引用的类型来绑定方法
( 注意:四大特性:抽象、封装、继承、多态 )
面试技巧:
每个人差不多十分钟事件,所以尽量答详细,不管问什么都尽量往老师总结的面向对象上靠,补充一些,要把东西表达清楚,多背点东西,不管什么知识点都要能说出来
- 本文作者: ACG kaka
- 本文链接: http://acgkaka.github.io/2020/11/06/2Java入门(二)面向对象编程 OOP/
- 版权声明: 文章均为个人整理,如有侵权,请联系删除。